﻿// Xshell Metadata Cache - Caches assemblies and types loaded by Xshell.
// 
// <copyright file="MetadataCache.cs" company="TaskyMedia LLC">
//   Copyright © 2010 TaskyMedia LLC
// </copyright>

namespace Xshell
{
    using System;
    using System.Collections.Generic;
    using System.Reflection;

    /// <summary>
    /// Default implementation of a cache of loaded assembly metadata and reflected types.
    /// </summary>
    public class MetadataCache : IMetadataCache
    {
        /// <summary>
        /// List of cached types.
        /// </summary>
        private LinkedList<Type> _types = new LinkedList<Type>();

        /// <summary>
        /// Initializes a new instance of the <see cref="MetadataCache"/> class.
        /// </summary>
        public MetadataCache()
        {
            Assembly execAssembly = Assembly.GetExecutingAssembly();
            Assembly callingAssembly = Assembly.GetCallingAssembly();
            Assembly entryAssembly = Assembly.GetEntryAssembly();

            if (!entryAssembly.Equals(callingAssembly) && !entryAssembly.Equals(execAssembly))
            {
                this.AddAssembly(entryAssembly);
            }

            if (!callingAssembly.Equals(execAssembly))
            {
                this.AddAssembly(callingAssembly);
            }

            this.AddAssembly(execAssembly);
        }

        /// <summary>
        /// Adds an assembly to the metadata cache and loads the Types from the assembly.
        /// </summary>
        /// <param name="assemblyToAdd">The assembly to add.</param>
        public void AddAssembly(Assembly assemblyToAdd)
        {
            foreach (Type type in assemblyToAdd.GetTypes())
            {
                if (!this._types.Contains(type))
                {
                    this._types.AddLast(type);
                }
            }
        }

        /// <summary>
        /// Gets a list of the cached types.
        /// </summary>
        /// <returns>Returns a list of the cached types</returns>
        public IEnumerable<Type> GetCachedTypes()
        {
            return this._types;
        }
    }
}
